#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Author          : ricsy
@File            : run.py
@Create Time     : 2025/6/2 20:32
@Last Modified   :
@Description     : https://github.com/sphinx-doc/sphinx-autobuild
"""
import argparse
import multiprocessing
import os
import platform
import sys
import webbrowser
from pathlib import Path
from shlex import quote

from dotenv import load_dotenv
from sphinx_autobuild import __main__ as autobuild

from src.settings import logger
from utils.config_processor import ConfigProcessor
from utils.environment_check import EnvironmentChecker


# 加载环境变量
load_dotenv()
# 获取配置信息
config = ConfigProcessor()

build = config.as_namespace("build")
host, port, open_browser = build.host, build.port, build.open_browser
source_dir, build_dir = build.source_dir, build.output_dir

static_dir = config.get_static_dir()
css_dir = static_dir / "css"


class SphinxAutoBuild:

    def __init__(self):
        self.args = self.parse_args()

    @staticmethod
    def parse_args():
        parser = argparse.ArgumentParser(description="Sphinx 自动化构建")
        parser.add_argument(
            "--open-browser",
            action="store_true",
            default=open_browser,
            help="完成后打开浏览器",
        )
        parser.add_argument("--port", type=int, default=int(port), help="监听端口")
        return parser.parse_args()

    @staticmethod
    def _format_system_command(command_args: list[str]) -> str:
        """
        格式化系统命令字符串
        :param command_args: 命令参数列表
        :returns: 格式化后的命令字符串
        """
        filtered_args = [arg for arg in command_args if arg.strip()]

        if platform.system() == "Windows":
            # Windows系统需要给路径加引号
            return " ".join(quote(str(arg)) for arg in filtered_args)
        return " ".join(filtered_args)

    def _build_asset_commands(self, debug_mode: bool) -> tuple[str, str]:
        """
        构建资源编译命令字符串
        :param debug_mode: 是否调试模式
        :returns: tuple: (scss_compile_command, js_build_command)
        """
        logger.info(f"{'🛠️ 调试模式' if debug_mode else '🚀 生产模式'}", 2)
        # SCSS 编译命令构建
        scss_compile_args = [
            sys.executable,  # 使用当前 Python 解释器，使用绝对路径
            str(Path("utils/scss_compiler.py").resolve()),  # 解析为绝对路径,
            "--debug" if debug_mode else "",  # 调试模式参数
        ]
        scss_compile_command = self._format_system_command(scss_compile_args)

        # JS 构建命令构建
        js_build_args = [
            sys.executable,
            str(Path("utils/js_compiler.py").resolve()),
            "--debug" if debug_mode else "",  # 调试模式参数
        ]
        js_build_command = self._format_system_command(js_build_args)

        return scss_compile_command, js_build_command

    def build_autobuild_args(self):
        """
        构建自动构建命令行参数
        :returns: 自动构建命令行参数列表
        """
        debug_mode = os.environ.get("DEBUG", "false").lower() == "true"
        scss_compile_command, js_build_command = self._build_asset_commands(debug_mode)

        # 计算并行任务数（-j auto）
        jobs = "auto" if multiprocessing.cpu_count() > 1 else "1"

        # 基础参数
        args = [
            "--watch",
            str(source_dir),
            "--port",
            str(self.args.port),
            "--host",
            str(host),
            "-j",
            jobs,
        ]

        # 从配置加载正则忽略规则
        for pattern in config.get_ignore_patterns():
            args.extend(["--ignore", f"{pattern}"])

        # 其他固定规则
        args.extend(
            [
                "--fresh",
                "--pre-build",
                scss_compile_command,
                "--pre-build",
                js_build_command,
                str(source_dir),
                str(build_dir),
            ]
        )
        return args

    def init_sphinx(self):
        # 1. 配置自动构建参数
        autobuild_args = self.build_autobuild_args()
        # 2. 启动自动构建
        if self.args.open_browser:
            webbrowser.open(f"http://localhost:{self.args.port}")
        autobuild.main(argv=autobuild_args)


if __name__ == "__main__":
    checker = EnvironmentChecker()
    if not checker.check_environment():
        sys.exit(1)
    SphinxAutoBuild().init_sphinx()
